/********************************************************/
/*	Copyright (C) 2016 Gong Li Bin			*/
/*	Project:	GlbCloud			*/
/*	Author:		gong_libin			*/
/*	Date:		2012_01_11			*/
/*	File:		MrSet.cpp			*/
/********************************************************/

#include "MrSet.h"

CMrSet::CMrSet()
{
	m_uiSize = 0;
	m_uiCount = 0;
	m_pSet = NULL;
	m_pCompare = NULL;
}

CMrSet::~CMrSet()
{
}

void* CMrSet::MrSetGetSet()
{
	return m_pSet;
}

UINT CMrSet::MrSetGetSize()
{
	return m_uiSize;
}

UINT CMrSet::MrSetGetCount()
{
	return m_uiCount;
}

MrSetCompPtr CMrSet::MrSetGetCompare()
{
	return m_pCompare;
}

void CMrSet::MrSetPutSet(void* pSet)
{
	m_pSet = pSet;

	return;
}

void CMrSet::MrSetPutSize(UINT uiSize)
{
	m_uiSize = uiSize;

	return;
}

void CMrSet::MrSetPutCount(UINT uiCount)
{
	m_uiCount = uiCount;

	return;
}

void CMrSet::MrSetDestroy()
{
	m_uiSize = 0;
	m_uiCount = 0;
	m_pCompare = NULL;
	if (NULL != m_pSet) {
		free(m_pSet);
		m_pSet = NULL;
	}
}

int CMrSet::MrSetInit(UINT uiTotal, UINT uiSize)
{
	int iReturn = MR_SUCCESS;

	m_uiSize = uiSize;
	m_pSet = (void*)malloc(uiTotal * uiSize);
	if (NULL != m_pSet) {
		memset(m_pSet, '\0', uiTotal * uiSize);
	}
	else {
		MR_ERROR("%s\n",strerror(errno));
		iReturn = MR_FAILURE;
	}

	return iReturn;
}

void CMrSet::MrSetClone(CMrSet& CSet)
{
	if (MR_SUCCESS == MrSetInit(CSet.MrSetGetCount(), CSet.MrSetGetSize())) {
		m_uiSize = CSet.MrSetGetSize();
		m_uiCount = CSet.MrSetGetCount();
		m_pCompare = CSet.MrSetGetCompare();
		memcpy(m_pSet, CSet.MrSetGetSet(), m_uiCount * m_uiSize);
	}

	return;
}

void CMrSet::MrSetCompare(MrSetCompPtr pCompare)
{
	m_pCompare = pCompare;

	return;
}

void* CMrSet::MrSetIndexGet(UINT uiIndex)
{
	void* pReturn = NULL;

	if (uiIndex >= 0) {
		pReturn = (UCHAR*)m_pSet + uiIndex * m_uiSize;
	}

	return pReturn;
}

void CMrSet::MrSetIndexErase(UINT uiIndex)
{
	if (uiIndex >= 0) {
		memset((UCHAR*)m_pSet + uiIndex * m_uiSize, '\0', m_uiSize);
	}

	return;
}

UINT CMrSet::MrSetIndexPut(UINT uiIndex, void* pData)
{
	if (uiIndex >= 0) {
		memcpy((UCHAR*)m_pSet + uiIndex * m_uiSize, pData, m_uiSize);
		if (uiIndex >= m_uiCount) {
			m_uiCount += 1;
		}
	}

	return m_uiCount;
}

void CMrSet::MrSetOrder()
{
	UCHAR* pucSrc = NULL;
	UCHAR* pucDst = NULL;

	pucSrc = pucDst = (UCHAR*)m_pSet;
	while ((pucSrc - (UCHAR*)m_pSet) / m_uiSize < m_uiCount) {
		while (false == MrSetIndexIsNull(pucDst) && (pucDst - (UCHAR*)m_pSet) / m_uiSize < m_uiCount) pucSrc = (pucDst += m_uiSize);
		while (true == MrSetIndexIsNull(pucSrc) && (pucSrc - (UCHAR*)m_pSet) / m_uiSize < m_uiCount) pucSrc += m_uiSize;
		if ((pucSrc - (UCHAR*)m_pSet) / m_uiSize < m_uiCount) {
			memcpy(pucDst, pucSrc, m_uiSize);
			memset(pucSrc, '\0', m_uiSize);
		}
	}
	m_uiCount = (pucDst - (UCHAR*)m_pSet) / m_uiSize;

	return;
}

void CMrSet::MrSetSort()
{
	qsort(m_pSet, m_uiCount, m_uiSize, *m_pCompare);

	return;
}

long CMrSet::MrSetIndex(void* pKey)
{
	void* pReturn = NULL;
	long lIndex = MR_FAILURE;

	pReturn = bsearch(pKey, m_pSet, m_uiCount, m_uiSize, *m_pCompare);
	if (NULL != pReturn) {
		lIndex = ((UCHAR*)pReturn - (UCHAR*)m_pSet) / m_uiSize;
	}

	return lIndex;
}

int CMrSet::MrSetSearch(void* pKey, void* pData)
{
	void* pReturn = NULL;

	pReturn = bsearch(pKey, m_pSet, m_uiCount, m_uiSize, *m_pCompare);
	if (NULL != pReturn) {
		memcpy(pData, pReturn, m_uiSize);
	}
	else {
		return MR_FAILURE;
	}

	return MR_SUCCESS;
}

bool CMrSet::MrSetIndexIsNull(UCHAR* pucCur)
{
	bool bReturn = true;
	UCHAR* pucBase = pucCur;

	while ((UINT)(pucCur - pucBase) < m_uiSize) {
		if ('\0' != *pucCur ++) {
			bReturn = false;
			break;
		}
	}

	return bReturn;
}
